home *** CD-ROM | disk | FTP | other *** search
/ Magnum One / Magnum One (Mid-American Digital) (Disc Manufacturing).iso / d13 / pj9_3.arc / ATOM.ASM < prev    next >
Assembly Source File  |  1991-10-07  |  7KB  |  334 lines

  1.     title    atom management routines
  2.     include    asm.inc
  3.  
  4.  
  5.     public    add_atom        ; add string atom to hash table
  6.     public    add_binary_atom        ; add binary atom to hash table
  7.     public    find_atom        ; search for string atom
  8.     public    find_binary_atom    ; search for binary atom
  9.     public    get_atom_name        ; copy atom text
  10.     public    init_atom_table        ; initialize atom table
  11.  
  12.  
  13. atom_str struc
  14.   at_atom_count        dw  ?        ; number of atoms (including NULL)
  15.   at_hash_divisor    dw  ?        ; prime divisor (table entry max)
  16.   at_hash_to_atom    dw  ?        ; offset of hash to atom index table
  17.   at_atom_to_text    dw  ?        ; offset of index to symbol text table
  18.   at_end_of_text    dw  ?        ; first free byte in symbol table
  19.   at_storage_size    dw  ?        ; dynamic storage byte count 
  20. atom_str ends
  21.  
  22.  
  23.     .data?
  24. atom_table    dw    ?        ; storage handle for hash table
  25.  
  26.  
  27.     .const
  28. ertx_bad_atom_index    db    'Bad atom index',0
  29. ertx_atom_table_full    db    'Atom table full',0
  30. ertx_atom_too_big    db    'Atom too big',0
  31.  
  32.  
  33.     .code
  34.     extn    global_calloc,global_free,global_lock,global_realloc
  35.     extn    global_unlock,save_most,strlen,strncpy,set_strerror
  36.  
  37.  
  38. ;;    add atom
  39. ;
  40. ;    entry    DS:SI    string to hash
  41. ;    exit    AX    atom index
  42. ;        Cf    if table full
  43. ;
  44. add_atom proc
  45.     push    cx            ; add null terminated string to
  46.     call    strlen            ;  atom table
  47.     call    add_binary_atom
  48.     pop    cx
  49.     ret
  50. add_atom endp
  51.  
  52.  
  53. ;;    add binary atom
  54. ;
  55. ;    entry    DS:SI    bytes to hash
  56. ;        CX    byte count (<256)
  57. ;    exit    AX    atom index
  58. ;        Cf    if table full or atom too big
  59. ;
  60. add_binary_atom proc
  61.     call    find_binary_atom
  62.     jnc    aba5            ;  if duplicate atom
  63.  
  64.     or    ch,ch
  65.     jnz    aba6            ;  if atom is too long
  66.  
  67.     call    save_most
  68.     mov    ax,ds            ; use ES:DI as atom pointer
  69.     mov    es,ax
  70.     mov    di,si
  71.     call    compute_atom_hash
  72.  
  73.     mov    bx,atom_table[bp]    ; get pointer to atom table
  74.     call    global_lock
  75.  
  76.     mov    ax,at_atom_count[si]    ; check atom count
  77.     inc    ax
  78.     cmp    ax,at_hash_divisor[si]
  79.     jae    aba7            ;  if too many symbols
  80.  
  81.     mov    ax,at_storage_size[si]    ; check empty text space
  82.     sub    ax,at_end_of_text[si]
  83.     cmp    cx,ax
  84.     jae    aba8            ;  if no space for new atom text
  85.  
  86. aba1:    mov    ax,at_end_of_text[si]    ; set text pointer in index table
  87.     mov    bx,at_atom_count[si]
  88.     add    bx,bx
  89.     add    bx,at_atom_to_text[si]
  90.     mov    [si+bx],ax
  91.  
  92.     mov    bx,ax            ; copy atom text
  93. aba2:    mov    al,es:[di]
  94.     mov    [si+bx],al
  95.     inc    di
  96.     inc    bx
  97.     loop    aba2
  98.     mov    [si+bx],cl        ;  (delimit atom text \0)
  99.     inc    bx
  100.     mov    at_end_of_text[si],bx    ;  update end of text pointer
  101.  
  102.     mov    cx,dx            ; find free entry in hash table
  103. aba3:    mov    ax,cx
  104.     inc    cx            ;  (bump hash for possible collision)
  105.     mov    dx,ZER0
  106.     div    at_hash_divisor[si]
  107.     mov    bx,dx
  108.     add    bx,bx
  109.     add    bx,at_hash_to_atom[si]
  110.     cmp    word ptr [si+bx],ZER0    ;  (Cf=0)
  111.     jnz    aba3            ;  if hash table collision
  112.  
  113.     mov    ax,at_atom_count[si]    ; set atom index in hash table
  114.     mov    [si+bx],ax
  115.     inc    ax            ; advance atom count
  116.     mov    at_atom_count[si],ax
  117.     dec    ax            ;  (Cf cleared above)
  118.  
  119. aba4:    mov    bx,atom_table[bp]    ; unlock atom table
  120.     call    global_unlock
  121. aba5:    ret
  122.  
  123. aba6:    lea    ax,ertx_atom_too_big    ; *Atom too big*
  124.     call    set_strerror
  125.     jmp    aba5
  126.  
  127. aba7:    lea    ax,ertx_atom_table_full    ; *Atom table full*
  128.     call    set_strerror
  129.     jmp    aba4
  130.  
  131. aba8:    mov    ax,at_storage_size[si]    ; increase size of atom table
  132.     add    ax,1024            ;  (by 1k)
  133.     jc    aba7            ;  if storage would exceed 64k
  134.  
  135.     push    cx
  136.     mov    cx,ax
  137.     call    global_unlock
  138.     call    global_realloc
  139.     pop    cx
  140.     jc    aba5            ;  if realloc failed
  141.     call    global_lock
  142.     mov    at_storage_size[si],ax
  143.     jmp    aba1
  144. add_binary_atom endp
  145.  
  146.  
  147. ;;    compute atom hash
  148. ;
  149. ;    entry    DS:SI    atom pointer
  150. ;        CX    byte count
  151. ;    exit    DX    case insensitive hash
  152. ;    uses    SI
  153. ;
  154. compute_atom_hash proc
  155.     push    cx
  156.     xor    dx,dx
  157.     jcxz    cah2            ; if null atom
  158. cah1:    xor    dl,[si]
  159.     inc    si
  160.     or    dl,20h            ; (make hash case insensitive)
  161.     add    dx,cx
  162.     rol    dx,1
  163.     rol    dx,1
  164.     rol    dx,1
  165.     rol    dx,1
  166.     loop    cah1
  167.     xor    dl,dh
  168. cah2:    pop    cx
  169.     ret
  170. compute_atom_hash endp
  171.  
  172.  
  173. ;;    find atom
  174. ;
  175. ;    entry    DS:SI    string to find
  176. ;    exit    AX    atom index
  177. ;        Cf    if not found
  178. ;
  179. find_atom proc
  180.     push    cx            ; find null terminated string in
  181.     call    strlen            ;  atom table
  182.     call    find_binary_atom
  183.     pop    cx
  184.     ret
  185. find_atom endp
  186.  
  187.  
  188. ;;    find binary atom
  189. ;
  190. ;    entry    DS:SI    bytes to hash
  191. ;        CX    byte count (<256)
  192. ;    exit    AX    atom index (or 0)
  193. ;        Cf    if not found
  194. ;
  195. find_binary_atom proc
  196.     xor    ax,ax            ; zero is null symbol index (Cf=0)
  197.     jcxz    fba3            ;  if null symbol
  198.     or    ch,ch
  199.     jnz    fba4            ;  if atom too big
  200.  
  201.     pushm    bx,dx,di,es
  202.     mov    ax,ds            ; ES:DI is target symbol text
  203.     mov    es,ax
  204.     mov    di,si
  205.     call    compute_atom_hash
  206.     inc    cx            ;   (include \0 in compares)
  207.  
  208.     mov    bx,atom_table[bp]    ; get pointer to atom table
  209.     call    global_lock
  210.     mov    bx,si
  211.  
  212. fba1:    xchg    ax,dx            ; divide hash by table size (prime #)
  213.     mov    si,ax
  214.     xor    dx,dx
  215.     div    at_hash_divisor[bx]
  216.     xchg    dx,si            ; use remainder as hash table index
  217.     inc    dx            ;  (advance to next hash entry)
  218.     add    si,si            ;  get atom index from hash table
  219.     add    si,bx
  220.     add    si,at_hash_to_atom[bx]
  221.  
  222.     lodsw
  223.     cmpx    ax,0
  224.     stc
  225.     je    fba2            ;  if entry empty, symbol not found
  226.  
  227.     mov    si,at_atom_to_text[bx]    ; translate index in AX to
  228.     add    si,ax            ;   displacement from beginning of
  229.     add    si,ax            ;   symbol text table
  230.     mov    si,[bx+si]
  231.     add    si,bx
  232.  
  233.     pushm    cx,di            ; compare target symbol & table entry
  234.     repe    cmpsb            ;  (CX includes \0 delimiter)
  235.     popm    di,cx
  236.     jne    fba1            ;  if no match, try next table entry
  237.  
  238. fba2:    mov    bx,atom_table[bp]
  239.     call    global_unlock
  240.  
  241.     dec    cx            ;  (restore CX adjusted for \0)
  242.     mov    dx,es
  243.     mov    ds,dx
  244.     mov    si,di
  245.     popm    es,di,dx,bx
  246. fba3:    ret
  247.  
  248. fba4:    lea    ax,ertx_atom_too_big    ; *Atom too big*
  249.     jmp    set_strerror
  250. find_binary_atom endp
  251.  
  252.  
  253. ;;    get atom name
  254. ;
  255. ;    entry    AX    atom index
  256. ;        CX    buffer size
  257. ;        ES:DI    output buffer
  258. ;    exit    DI    updated (points to \0)
  259. ;        CX    updated
  260. ;        Cf    if bad atom index
  261. ;    uses    AX
  262. ;
  263. get_atom_name proc
  264.     pushm    bx,si,ds
  265.     mov    bx,atom_table[bp]    ; access atom table
  266.     call    global_lock
  267.  
  268.     cmp    ax,at_atom_count[si]    ; check atom index
  269.     jae    gan1            ;  if too high - bad index
  270.  
  271.     add    ax,ax            ; use atom index to find atom text
  272.     mov    bx,ax
  273.     add    bx,at_atom_to_text[si]
  274.     mov    bx,[si+bx]
  275.     mov    si,bx
  276.  
  277.     call    strncpy            ; write atom to output buffer
  278.     clc
  279.     jmp    gan2
  280.  
  281. gan1:    lea    ax,ertx_bad_atom_index    ; *bad atom index*
  282.     call    set_strerror
  283.  
  284. gan2:    mov    bx,atom_table[bp]    ; unlock atom table (Cf unchanged)
  285.     call    global_unlock
  286.     popm    ds,si,bx
  287.     ret
  288. get_atom_name endp
  289.  
  290.  
  291. ;;    init atom table
  292. ;
  293. ;    entry    AX    prime number approximate twice maximum atom count
  294. ;    exit    Cf    if no memory
  295. ;    uses    AX
  296. ;
  297. init_atom_table proc
  298.     call    save_most
  299.     mov    di,ax            ; compute table size
  300.     mov    dx,4            ;  (space for atom_to_text and
  301.     mul    dx            ;   hash_to_atom tables)
  302.     add    ax,size atom_str+1024    ;  (space for atom_str & symbol_table)
  303.     adc    dx,dx
  304.     stc
  305.     jnz    iat1            ;  if table > 64k
  306.     mov    cx,ax
  307.  
  308.     mov    bx,ZER0            ; free old atom table
  309.     xchg    bx,atom_table[bp]
  310.     call    global_free        ;  (OK if BX==0)
  311.  
  312.     call    global_calloc        ; allocate and zero atom table
  313.     jc    iat1            ;  if not enough memory
  314.     mov    atom_table[bp],bx
  315.  
  316.     call    global_lock
  317.     mov    at_storage_size[si],ax
  318.     mov    at_atom_count[si],1
  319.     mov    at_hash_divisor[si],di
  320.     mov    ax,size atom_str    ; hash_to_atom table follows structure
  321.     mov    at_hash_to_atom[si],ax
  322.     add    di,di            ; followed by atom_to_text table
  323.     add    ax,di
  324.     mov    at_atom_to_text[si],ax
  325.     add    ax,di            ; symbol table is last
  326.     inc    ax
  327.     mov    at_end_of_text[si],ax
  328.  
  329.     call    global_unlock
  330. iat1:    ret
  331. init_atom_table endp
  332.  
  333.     end
  334.